
// Copyright Epic Games, Inc. All Rights Reserved.

#include "zencore/zencore.h"

#if ZEN_PLATFORM_WINDOWS
#	include <zencore/except.h>
#	include "zencore/windows.h"

namespace zen::windows {

bool
IsRunningOnWine()
{
	HMODULE NtDll = GetModuleHandleA("ntdll.dll");

	if (NtDll)
	{
		return !!GetProcAddress(NtDll, "wine_get_version");
	}

	return false;
}

FileMapping::FileMapping(_In_ FileMapping& orig)
{
	m_pData	   = NULL;
	m_hMapping = NULL;

	HRESULT hr = CopyFrom(orig);
	if (FAILED(hr))
		zen::ThrowSystemException(hr, "Failed to clone FileMapping");
}

FileMapping&
FileMapping::operator=(_In_ FileMapping& orig)
{
	HRESULT hr = CopyFrom(orig);
	if (FAILED(hr))
		zen::ThrowSystemException(hr, "Failed to clone FileMapping");

	return *this;
}

HRESULT
FileMapping::CopyFrom(_In_ FileMapping& orig) throw()
{
	if (this == &orig)
		return S_OK;

	ZEN_ASSERT(m_pData == NULL);
	ZEN_ASSERT(m_hMapping == NULL);
	ZEN_ASSERT(orig.m_pData != NULL);

	m_dwViewDesiredAccess = orig.m_dwViewDesiredAccess;
	m_nOffset.QuadPart	  = orig.m_nOffset.QuadPart;
	m_nMappingSize		  = orig.m_nMappingSize;

	if (!::DuplicateHandle(GetCurrentProcess(), orig.m_hMapping, GetCurrentProcess(), &m_hMapping, NULL, TRUE, DUPLICATE_SAME_ACCESS))
		return MapHresultFromLastError();

	m_pData = ::MapViewOfFileEx(m_hMapping, m_dwViewDesiredAccess, m_nOffset.HighPart, m_nOffset.LowPart, m_nMappingSize, NULL);
	if (m_pData == NULL)
	{
		HRESULT hr;

		hr = MapHresultFromLastError();
		::CloseHandle(m_hMapping);
		m_hMapping = NULL;
		return hr;
	}

	return S_OK;
}

}  // namespace zen::windows
#endif
